{*******************************************************************************
* The contents of this file are used with permission, subject to the Mozilla   *
* Public License Version 1.1 (the "License"); you may not use this file except *
* in compliance with the License. You may obtain a copy of the License at      *
* http://www.mozilla.org/MPL/                                                  *
*                                                                              *
* Software distributed under the License is distributed on an "AS IS" basis,   *
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for *
* the specific language governing rights and limitations under the License.    *
*                                                                              *
* The Original Code is distributed as part of the "mediate" product and is     *
* Copyright (C) @home media limited. All Rights Reserved.                      *
*                                                                              *
* Email: support@athomemedia.co.uk                                             *
* Web:   http://www.athomemedia.co.uk                                          *
*******************************************************************************}

unit DesignerPropsEdit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ImgList, PngImageList, ComCtrls, ExtCtrls, StdCtrls, UIObjects,
  ActnList;

type
  TfrmObjectProperties = class(TForm)
    pbHeader: TPaintBox;
    lbCaption: TLabel;
    lbAction: TLabel;
    btCancel: TButton;
    pnItemDetails: TPanel;
    Bevel1: TBevel;
    Bevel3: TBevel;
    btOkay: TButton;
    pgPages: TPageControl;
    tsAction: TTabSheet;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    edActionDescription: TEdit;
    ecActionFunction: TComboBox;
    edActionTarget: TEdit;
    edActionParameter: TEdit;
    cbActionFinal: TCheckBox;
    ecActionName: TComboBox;
    tsMeta: TTabSheet;
    Label6: TLabel;
    Label7: TLabel;
    mmMetaValue: TMemo;
    ecMetaName: TComboBox;
    tsFont: TTabSheet;
    Label8: TLabel;
    ecTypeface: TComboBox;
    ecFontColour: TComboBox;
    Label9: TLabel;
    ecShadowColour: TComboBox;
    Label10: TLabel;
    ecOutlineColour: TComboBox;
    Label11: TLabel;
    edFontSize: TEdit;
    Label12: TLabel;
    edOutlineWidth: TEdit;
    edShadowX: TEdit;
    edShadowY: TEdit;
    Label13: TLabel;
    Label14: TLabel;
    Label15: TLabel;
    udOutlineWidth: TUpDown;
    udShadowX: TUpDown;
    udFontSize: TUpDown;
    udShadowY: TUpDown;
    cbBold: TCheckBox;
    cbShadow: TCheckBox;
    cbItalic: TCheckBox;
    cbUnderline: TCheckBox;
    cbOutline: TCheckBox;
    cbGlow: TCheckBox;
    tsAnimation: TTabSheet;
    Label16: TLabel;
    ecAnimationType: TComboBox;
    Label17: TLabel;
    cbAnimationConcurrent: TCheckBox;
    cbAnimationBreakable: TCheckBox;
    edAnimationDuration: TEdit;
    udAnimationDuration: TUpDown;
    cbAnimationPersistent: TCheckBox;
    edAnimationParam1: TEdit;
    edAnimationParam2: TEdit;
    edAnimationParam3: TEdit;
    txAnimationParam1: TLabel;
    txAnimationParam2: TLabel;
    txAnimationParam3: TLabel;
    ecAnimationParam1: TComboBox;
    ecAnimationParam2: TComboBox;
    tsMacro: TTabSheet;
    Label18: TLabel;
    Label19: TLabel;
    Label20: TLabel;
    ecMacroFunction: TComboBox;
    edMacroTarget: TEdit;
    edMacroParameter: TEdit;
    tsState: TTabSheet;
    Label21: TLabel;
    ecStateType: TComboBox;
    Label22: TLabel;
    ecStateObject: TComboBox;
    Label23: TLabel;
    ecStateName: TComboBox;
    tsPosition: TTabSheet;
    Label24: TLabel;
    edPositionX: TEdit;
    udPositionX: TUpDown;
    Label25: TLabel;
    edPositionY: TEdit;
    udPositionY: TUpDown;
    Label26: TLabel;
    edPositionComment: TEdit;
    tsFillColour: TTabSheet;
    Label27: TLabel;
    edFillPosition: TEdit;
    udFillPosition: TUpDown;
    Label28: TLabel;
    ecFillColour: TComboBox;
    procedure pbHeaderPaint(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure UIObjectListSelect(Sender: TObject);
    procedure btOkayClick(Sender: TObject);
    procedure UIObjectChanged(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ecTypefaceDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure ecFontColourDrawItem(Control: TWinControl; Index: Integer;
      Rect: TRect; State: TOwnerDrawState);
    procedure ecTypefaceMeasureItem(Control: TWinControl; Index: Integer;
      var Height: Integer);
    procedure ecAnimationTypeSelect(Sender: TObject);
    procedure ecStateTypeSelect(Sender: TObject);
    procedure btCancelClick(Sender: TObject);
  private
    { Private declarations }
    FHeaderImages: TPngImageList;
    FOwner: TAHMUIObjectList;
    FInstance: TAHMUIObject;
    FAddingMode: Boolean;
    FContext: String;
    FState: String;
    procedure LoadImages;
  protected
    { Protected declarations }
    procedure ConfigureForm;
    procedure PopulateForm;
    procedure ValidateForm;
    procedure PopulateObject;
    procedure PopulateCombo(Combo: TComboBox; Instance: TAHMUIObject;
                            List: TAHMUIObjectList; Optional: Boolean = False); overload;
    procedure PopulateCombo(Combo: TComboBox; Value: String;
                            List: TAHMUIObjectList; Optional: Boolean = False); overload;
    function GetComboSelection(Combo: TComboBox): TObject;
    function GetComboValue(Combo: TComboBox): String;
    procedure PopulateActionControls;
    procedure PopulateMetaControls;
    procedure PopulateFontControls;
    procedure PopulateMacroControls;
    procedure PopulatePositionControls;
    procedure PopulateAnimationControls;
    procedure PopulateFillColourControls;
    procedure PopulateStateControls;
    function ValidateActionControls: Boolean;
    function ValidateMetaControls: Boolean;
    function ValidateFontControls: Boolean;
    function ValidateMacroControls: Boolean;
    function ValidatePositionControls: Boolean;
    function ValidateAnimationControls: Boolean;
    function ValidateFillColourControls: Boolean;
    function ValidateStateControls: Boolean;
    procedure PopulateActionObject;
    procedure PopulateMetaObject;
    procedure PopulateFontObject;
    procedure PopulateMacroObject;
    procedure PopulatePositionObject;
    procedure PopulateAnimationObject;
    procedure PopulateFillColourObject;
    procedure PopulateStateObject;
    procedure ConfigureAnimationControls;
    procedure ConfigureStateControls;
  public
    { Public declarations }
    property ListOwner: TAHMUIObjectList read FOwner write FOwner;
    property Instance: TAHMUIObject read FInstance write FInstance;
    property AddingMode: Boolean read FAddingMode write FAddingMode;
    property ObjectState: String read FState write FState;
    class function AddObject(var Instance: TAHMUIObject; Owner: TAHMUIObjectList): Boolean;
    class function AddStateObject(var State: String; var Instance: TAHMUIObject; Owner: TAHMUIObjectList): Boolean;
    class function EditObject(Instance: TAHMUIObject; Owner: TAHMUIObjectList): Boolean;
    class function EditStateObject(var State: String; var Instance: TAHMUIObject; Owner: TAHMUIObjectList): Boolean;
  end;


implementation

{$R *.dfm}

uses ApplicationManager, Actions, MetaValues, Fonts, Colours, Animators, Fills,
     Macros, Layouts, DesignerPropsInspector, TypInfo, TagNames, AHMTypes;

var
  FormInstance: TfrmObjectProperties;

//-----------------------------------------------------------------------------
//----------------------------- Class Functions -------------------------------
//-----------------------------------------------------------------------------

class function TfrmObjectProperties.AddObject(var Instance: TAHMUIObject; Owner: TAHMUIObjectList): Boolean;
begin
  // Set default result - failed
  Result := False;

  // Create a singleton form instance
  if not Assigned(FormInstance) then
  begin
    FormInstance := TfrmObjectProperties.Create(Application.MainForm);
    FormInstance.PopupParent := Application.MainForm;
  end;

  FormInstance.ListOwner := Owner;
  FormInstance.Instance := Owner.ChildClass.Create('');
  FormInstance.AddingMode := True;

  if FormInstance.ShowModal = mrOK then
  begin
    FormInstance.PopulateObject;
    Instance := FormInstance.Instance;
    Instance.Owner := Owner;
    Owner.Add(Instance);
    Result := True;
  end
  else
    FormInstance.Instance.Free;
end;

class function TfrmObjectProperties.AddStateObject(var State: String; var Instance: TAHMUIObject; Owner: TAHMUIObjectList): Boolean;
begin
  // Set default result - failed
  Result := False;

  // Create a singleton form instance
  if not Assigned(FormInstance) then
  begin
    FormInstance := TfrmObjectProperties.Create(Application.MainForm);
    FormInstance.PopupParent := Application.MainForm;
  end;

  FormInstance.ListOwner := Owner;
  FormInstance.ObjectState := '';
  FormInstance.AddingMode := True;

  if FormInstance.ShowModal = mrOK then
  begin
    FormInstance.PopulateObject;
    Instance := FormInstance.Instance;
    State := FormInstance.ObjectState;
    Result := True;
  end;
end;

class function TfrmObjectProperties.EditObject(Instance: TAHMUIObject; Owner: TAHMUIObjectList): Boolean;
begin
  // Set default result - failed
  Result := False;

  // Ensure we have a valid object instance passed
  if not Assigned(Instance) then Exit;

  // Create a singleton form instance
  if not Assigned(FormInstance) then
  begin
    FormInstance := TfrmObjectProperties.Create(Application.MainForm);
    FormInstance.PopupParent := Application.MainForm;
  end;

  FormInstance.ListOwner := Owner;
  FormInstance.Instance := Instance;
  FormInstance.AddingMode := False;

  if FormInstance.ShowModal = mrOK then
  begin
    FormInstance.PopulateObject;
    Result := True;
  end;
end;

class function TfrmObjectProperties.EditStateObject(var State: String; var Instance: TAHMUIObject; Owner: TAHMUIObjectList): Boolean;
begin
  // Set default result - failed
  Result := False;

  // Create a singleton form instance
  if not Assigned(FormInstance) then
  begin
    FormInstance := TfrmObjectProperties.Create(Application.MainForm);
    FormInstance.PopupParent := Application.MainForm;
  end;

  FormInstance.ListOwner := Owner;
  FormInstance.Instance := Instance;
  FormInstance.ObjectState := State;
  FormInstance.AddingMode := False;

  if FormInstance.ShowModal = mrOK then
  begin
    FormInstance.PopulateObject;
    Instance := FormInstance.Instance;
    State := FormInstance.ObjectState;
    Result := True;
  end;
end;

//-----------------------------------------------------------------------------
//----------------------------- Form Events -----------------------------------
//-----------------------------------------------------------------------------

procedure TfrmObjectProperties.FormCreate(Sender: TObject);
begin
  // Create and populate PNG image list
  FHeaderImages := TPngImageList.Create(Self);
  LoadImages;
end;

procedure TfrmObjectProperties.FormShow(Sender: TObject);
begin
  ConfigureForm;
end;

//-----------------------------------------------------------------------------
//----------------------------- Control Events --------------------------------
//-----------------------------------------------------------------------------

procedure TfrmObjectProperties.btCancelClick(Sender: TObject);
begin
  ModalResult := mrCancel;
end;

procedure TfrmObjectProperties.btOkayClick(Sender: TObject);
begin
  ModalResult := mrOK;
end;

procedure TfrmObjectProperties.UIObjectChanged(Sender: TObject);
begin
  ValidateForm;
end;

procedure TfrmObjectProperties.UIObjectListSelect(Sender: TObject);
var
  i: Integer;
begin
  with Sender as TComboBox do
  begin
    i := Items.IndexOf(Text);
    if i < 0 then
      Hint := ''
    else if Items.Objects[i] is TAHMUIObject then
      Hint := TAHMUIObject(Items.Objects[i]).Description
    else
      Hint := '';
  end;

  ValidateForm;
end;

procedure TfrmObjectProperties.pbHeaderPaint(Sender: TObject);
begin
  with pbHeader do
  begin
    // Draw background
    Canvas.Brush.Color := clWhite;
    Canvas.FillRect(GetClientRect);
    // Draw appropriate header image
    FHeaderImages.Draw(Canvas, ClientWidth - FHeaderImages.Width, 0, 0);
  end;
end;

procedure TfrmObjectProperties.ecAnimationTypeSelect(Sender: TObject);
begin
  ConfigureAnimationControls;
end;

procedure TfrmObjectProperties.ecFontColourDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
begin
  with TComboBox(Control) do
  begin
    if odSelected in State then Canvas.Brush.Color := clHighlight;
    Canvas.FillRect(Rect);
    Rect.Top := Rect.Top + 1;
    Rect.Bottom := Rect.Bottom - 1;
    PaintColourValue(TAHMUIObject(Items.Objects[Index]), Items[Index], Canvas, Rect);
  end;
end;

procedure TfrmObjectProperties.ecStateTypeSelect(Sender: TObject);
begin
  ConfigureStateControls;
end;

procedure TfrmObjectProperties.ecTypefaceDrawItem(Control: TWinControl;
  Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
  h: Integer;
begin
  with TComboBox(Control) do
  begin
    Canvas.FillRect(Rect);
    if odComboBoxEdit in State then ParentFont := True
                               else Canvas.Font.Name := Items[Index];
    h := Canvas.TextHeight(Items[Index]);
    Rect.Left := Rect.Left + 2;
    Rect.Top := Rect.Top + (Rect.Bottom - Rect.Top - h) div 2;
    Canvas.TextRect(Rect, Rect.Left, Rect.Top, Items[Index]);
  end;
end;

procedure TfrmObjectProperties.ecTypefaceMeasureItem(Control: TWinControl;
  Index: Integer; var Height: Integer);
begin
  with TComboBox(Control) do
    Height := Canvas.TextHeight(Items[Index]);
end;

//-----------------------------------------------------------------------------
//-------------------------- User Interface Update ----------------------------
//-----------------------------------------------------------------------------

procedure TfrmObjectProperties.ConfigureForm;
var
  sCaption: String;
begin
  // Customise display for selected object type
  if FOwner is TAHMUIStateObjectList then
    sCaption := TAHMUIStateObjectList(FOwner).DisplayClassName
  else
    sCaption := FOwner.ClassName;
  if sCaption = '' then sCaption := 'Object';
  FContext := Lowercase(sCaption);

  if FAddingMode then
  begin
    Caption := 'Add ' + sCaption;
    lbCaption.Caption := 'Add a new ' + FContext;
    lbAction.Caption := 'You may enter details for the new ' + FContext + ' below';
  end
  else
  begin
    Caption := 'Edit ' + sCaption;
    lbCaption.Caption := 'Edit ' + FContext + ' properties';
    lbAction.Caption := 'You may modify the ' + FContext + ' below';
  end;

  // Populate form controls
  PopulateForm;
  ValidateForm;

  // Start focus in the page control
  pgPages.SetFocus;
  SelectNext(pgPages, True, True);
end;

procedure TfrmObjectProperties.PopulateForm;
var
  i: Integer;
begin
  // Hide tabs for all pages except the active one
  for i := 0 to Pred(pgPages.PageCount) do
    pgPages.Pages[i].TabVisible := False;

  // Display appropriate page of controls
  if FOwner is TAHMActionList then PopulateActionControls
  else if FOwner is TAHMMetaValueList then PopulateMetaControls
  else if FOwner is TAHMFontList then PopulateFontControls
  else if FOwner is TAHMMacroFunctionList then PopulateMacroControls
  else if FOwner is TAHMLayoutPositionList then PopulatePositionControls
  else if FOwner is TAHMAnimationList then PopulateAnimationControls
  else if FOwner is TAHMFillColourList then PopulateFillColourControls
  else if FOwner is TAHMUIStateObjectList then PopulateStateControls;

  if Assigned(pgPages.ActivePage) then pgPages.ActivePage.TabVisible := True;
end;

procedure TfrmObjectProperties.ValidateForm;
var
  Valid: Boolean;
begin
  // Validate appropriate object properties
  if FOwner is TAHMActionList then Valid := ValidateActionControls
  else if FOwner is TAHMMetaValueList then Valid := ValidateMetaControls
  else if FOwner is TAHMFontList then Valid := ValidateFontControls
  else if FOwner is TAHMMacroFunctionList then Valid := ValidateMacroControls
  else if FOwner is TAHMLayoutPositionList then Valid := ValidatePositionControls
  else if FOwner is TAHMAnimationList then Valid := ValidateAnimationControls
  else if FOwner is TAHMFillColourList then Valid := ValidateFillColourControls
  else if FOwner is TAHMUIStateObjectList then Valid := ValidateStateControls
  else Valid := True;

  btOkay.Enabled := Valid;
end;

procedure TfrmObjectProperties.PopulateObject;
begin
  // Populate appropriate object properties
  if FOwner is TAHMActionList then PopulateActionObject
  else if FOwner is TAHMMetaValueList then PopulateMetaObject
  else if FOwner is TAHMFontList then PopulateFontObject
  else if FOwner is TAHMMacroFunctionList then PopulateMacroObject
  else if FOwner is TAHMLayoutPositionList then PopulatePositionObject
  else if FOwner is TAHMAnimationList then PopulateAnimationObject
  else if FOwner is TAHMFillColourList then PopulateFillColourObject
  else if FOwner is TAHMUIStateObjectList then PopulateStateObject;
end;

procedure TfrmObjectProperties.PopulateCombo(Combo: TComboBox; Instance: TAHMUIObject;
                                             List: TAHMUIObjectList; Optional: Boolean);
begin
  // Delegate to method below
  if Assigned(Instance) then PopulateCombo(Combo, Instance.Name, List, Optional)
                        else PopulateCombo(Combo, '', List, Optional);
end;

procedure TfrmObjectProperties.PopulateCombo(Combo: TComboBox; Value: String;
                                             List: TAHMUIObjectList; Optional: Boolean);
begin
  with Combo do
  begin
    Items.Clear;
    if Optional then Items.Add(EMPTY_UIOBJECT_NAME);
    if Assigned(List) then List.ListObjects(Items);

    ItemIndex := Items.IndexOf(Value);
    if Style = csDropDown then Text := Value
    else if Optional and (Value = '') then ItemIndex := 0;

    // Initialise hint for combo
    UIObjectListSelect(Combo);
  end;
end;

function TfrmObjectProperties.GetComboSelection(Combo: TComboBox): TObject;
begin
  with Combo do
    if ItemIndex <> -1 then Result := Items.Objects[ItemIndex]
                       else Result := nil;
end;

function TfrmObjectProperties.GetComboValue(Combo: TComboBox): String;
begin
  with Combo do
    if Text = EMPTY_UIOBJECT_NAME then Result := '' else Result := Text;
end;

procedure TfrmObjectProperties.PopulateActionControls;
begin
  pgPages.ActivePage := tsAction;
  with ApplicationManagerInstance, FInstance as TAHMAction do
  begin
    PopulateCombo(ecActionName, Name, FunctionDescriptor.ActionList);
    edActionDescription.Text := Description;
    PopulateCombo(ecActionFunction, ActionFunction, FunctionDescriptor.FunctionList);
    edActionTarget.Text := TargetName;
    edActionParameter.Text := Parameter;
    cbActionFinal.Checked := FinalAction;
  end;
end;

procedure TfrmObjectProperties.PopulateMetaControls;
begin
  pgPages.ActivePage := tsMeta;
  with ApplicationManagerInstance, FInstance as TAHMMetaValue do
  begin
    PopulateCombo(ecMetaName, Name, MetaDescriptor.MetaList);
    mmMetaValue.Text := Value;
  end;
end;

procedure TfrmObjectProperties.PopulateFontControls;
begin
  pgPages.ActivePage := tsFont;
  with ApplicationManagerInstance.ThemeManager, FInstance as TAHMFont do
  begin
    ecTypeface.Items.Assign(Screen.Fonts);
    ecTypeface.ItemIndex := ecTypeface.Items.IndexOf(Typeface);
    PopulateCombo(ecFontColour, Colour, VisualDescriptor.ColourList, True);
    PopulateCombo(ecShadowColour, ShadowColour, VisualDescriptor.ColourList, True);
    PopulateCombo(ecOutlineColour, OutlineColour, VisualDescriptor.ColourList, True);
    udFontSize.Position := VirtualSize;
    udOutlineWidth.Position := VirtualOutlineWidth;
    udShadowX.Position := VirtualShadowXOffset;
    udShadowY.Position := VirtualShadowYOffset;
    cbBold.Checked := Bold;
    cbItalic.Checked := Italic;
    cbUnderline.Checked := Underline;
    cbShadow.Checked := Shadow;
    cbOutline.Checked := Outline;
    cbGlow.Checked := Glow;
  end;
end;

procedure TfrmObjectProperties.PopulateMacroControls;
begin
  pgPages.ActivePage := tsMacro;
  with ApplicationManagerInstance, FInstance as TAHMMacroFunction do
  begin
    PopulateCombo(ecMacroFunction, FunctionName, FunctionDescriptor.FunctionList);
    edMacroTarget.Text := TargetName;
    edMacroParameter.Text := Parameter;
  end;
end;

procedure TfrmObjectProperties.PopulatePositionControls;
begin
  pgPages.ActivePage := tsPosition;
  with ApplicationManagerInstance, FInstance as TAHMLayoutPosition do
  begin
    udPositionX.Position := VirtualX;
    udPositionY.Position := VirtualY;
    edPositionComment.Text := Comment;
  end;
end;

procedure TfrmObjectProperties.PopulateAnimationControls;
begin
  pgPages.ActivePage := tsAnimation;
  with ApplicationManagerInstance.ThemeManager, FInstance as TAHMAnimation do
  begin
    ecAnimationType.ItemIndex := Pred(Ord(AnimationType));
    udAnimationDuration.Position := Duration;
    cbAnimationConcurrent.Checked := Concurrent;
    cbAnimationBreakable.Checked := Breakable;
    cbAnimationPersistent.Checked := Persistent;
  end;

  ConfigureAnimationControls;
end;

procedure TfrmObjectProperties.PopulateFillColourControls;
var
  Colours: TAHMUIObjectList;
begin
  pgPages.ActivePage := tsFillColour;
  with ApplicationManagerInstance.ThemeManager, FOwner as TAHMUIStateObjectList do
  begin
    udFillPosition.Position := StrToIntDef(FState, 0);

    // Populate colour list
    Colours := VisualDescriptor.ColourList;
    if FAddingMode then PopulateCombo(ecFillColour, nil, Colours, True)
                   else PopulateCombo(ecFillColour, FInstance, Colours, True);
  end;
end;

procedure TfrmObjectProperties.PopulateStateControls;
var
  i: TAHMUIObjectType;
  StateInfo: String;
begin
  pgPages.ActivePage := tsState;
  with ApplicationManagerInstance.ThemeManager, FOwner as TAHMUIStateObjectList do
  begin
    // Configure combo box for fixed or custom states as required
    if StateType = stCustom then ecStateName.Style := csDropDown
                            else ecStateName.Style := csDropDownList;
    ecStateName.Items.Clear;
    ListStates(ecStateName.Items);
    ecStateName.ItemIndex := ecStateName.Items.IndexOf(FState);
    if StateType = stCustom then ecStateName.Text := FState;

    ecStateType.Items.Clear;
    for i in ObjectTypes do
    begin
      // Use RTTI inspection to determine object type display name
      StateInfo := GetEnumName(TypeInfo(TAHMUIObjectType), Integer(i));
      StateInfo := Copy(StateInfo, 3, Length(StateInfo));
      ecStateType.Items.AddObject(StateInfo, TObject(i));
      // Populate default state in add mode, or selected state in edit
      if (FAddingMode and (ecStateType.ItemIndex = -1)) or
         ((not FAddingMode) and (FInstance.ObjectType = i)) then
        ecStateType.ItemIndex := ecStateType.Items.Count - 1;
    end;

    ConfigureStateControls;
  end;
end;

function TfrmObjectProperties.ValidateActionControls: Boolean;
begin
  Result := (ecActionName.Text <> '') and (ecActionFunction.ItemIndex <> -1);
end;

function TfrmObjectProperties.ValidateMetaControls: Boolean;
begin
  Result := ecMetaName.Text <> '';
end;

function TfrmObjectProperties.ValidateFontControls: Boolean;
begin
  Result := True;
end;

function TfrmObjectProperties.ValidateMacroControls: Boolean;
begin
  Result := ecMacroFunction.ItemIndex <> -1;
end;

function TfrmObjectProperties.ValidatePositionControls: Boolean;
begin
  Result := True;
end;

function TfrmObjectProperties.ValidateAnimationControls: Boolean;
begin
  Result := ecAnimationType.ItemIndex <> -1;
end;

function TfrmObjectProperties.ValidateFillColourControls: Boolean;
begin
  Result := ecFillColour.ItemIndex > 0;
end;

function TfrmObjectProperties.ValidateStateControls: Boolean;
begin
  Result := (ecStateName.Text <> '') and (ecStateObject.ItemIndex > 0);
end;

procedure TfrmObjectProperties.PopulateActionObject;
begin
  with FInstance as TAHMAction do
  begin
    Rename(ecActionName.Text);
    Description := edActionDescription.Text;
    ActionFunction := ecActionFunction.Text;
    TargetName := edActionTarget.Text;
    Parameter := edActionParameter.Text;
    FinalAction := cbActionFinal.Checked;
  end;
end;

procedure TfrmObjectProperties.PopulateMetaObject;
begin
  with FInstance as TAHMMetaValue do
  begin
    Rename(ecMetaName.Text);
    Value := mmMetaValue.Text;
  end;
end;

procedure TfrmObjectProperties.PopulateFontObject;
begin
  with FInstance as TAHMFont do
  begin
    Typeface := ecTypeface.Text;
    Colour := TAHMColour(GetComboSelection(ecFontColour));
    ShadowColour := TAHMColour(GetComboSelection(ecShadowColour));
    OutlineColour := TAHMColour(GetComboSelection(ecOutlineColour));
    VirtualSize := udFontSize.Position;
    VirtualOutlineWidth := udOutlineWidth.Position;
    VirtualShadowXOffset := udShadowX.Position;
    VirtualShadowYOffset := udShadowY.Position;
    Bold := cbBold.Checked;
    Italic := cbItalic.Checked;
    Underline := cbUnderline.Checked;
    Shadow := cbShadow.Checked;
    Outline := cbOutline.Checked;
    Glow := cbGlow.Checked;
  end;
end;

procedure TfrmObjectProperties.PopulateMacroObject;
begin
  with FInstance as TAHMMacroFunction do
  begin
    FunctionName := ecMacroFunction.Text;
    TargetName := edMacroTarget.Text;
    Parameter := edMacroParameter.Text;
  end;
end;

procedure TfrmObjectProperties.PopulatePositionObject;
begin
  with FInstance as TAHMLayoutPosition do
  begin
    VirtualX := udPositionX.Position;
    VirtualY := udPositionY.Position;
    Comment := edPositionComment.Text;
  end;
end;

procedure TfrmObjectProperties.PopulateAnimationObject;
begin
  with FInstance as TAHMAnimation do
  begin
    AnimationType := TAHMAnimationType(Succ(ecAnimationType.ItemIndex));
    Duration := udAnimationDuration.Position;
    Concurrent := cbAnimationConcurrent.Checked;
    Breakable := cbAnimationBreakable.Checked;
    Persistent := cbAnimationPersistent.Checked;

    // Configure parameters for selected animation
    case AnimationType of
      atSize:
      begin
        AddParameter(ANIM_PARAM_START_SIZE, edAnimationParam1.Text);
        AddParameter(ANIM_PARAM_FINISH_SIZE, edAnimationParam2.Text);
      end;
      atSlide, atRotate:
      begin
        AddParameter(ANIM_PARAM_START_POS, GetComboValue(ecAnimationParam1));
        AddParameter(ANIM_PARAM_FINISH_POS, GetComboValue(ecAnimationParam2));
      end;
      atScale:
      begin
        AddParameter(ANIM_PARAM_START_SCALE, edAnimationParam1.Text);
        AddParameter(ANIM_PARAM_FINISH_SCALE, edAnimationParam2.Text);
      end;
      atFadeIn, atFadeOut:
      begin
        AddParameter(ANIM_PARAM_START_GAMMA, GetComboValue(ecAnimationParam1));
        AddParameter(ANIM_PARAM_FINISH_GAMMA, GetComboValue(ecAnimationParam2));
      end;
      atMacro:
      begin
        AddParameter(ANIM_PARAM_MACRO_NAME, GetComboValue(ecAnimationParam1));
      end;
      atFunction:
      begin
        AddParameter(ANIM_PARAM_FUNCTION_NAME, GetComboValue(ecAnimationParam1));
        AddParameter(ANIM_PARAM_FUNCTION_TARGET, edAnimationParam2.Text);
        AddParameter(ANIM_PARAM_FUNCTION_PARAM, edAnimationParam3.Text);
      end;
    end;
  end;
end;

procedure TfrmObjectProperties.PopulateFillColourObject;
var
  Colours: TAHMUIObjectList;
  Colour: TAHMUIObject;
begin
  // Remove existing colour object instance from list
  if not FAddingMode then TAHMFillColourList(FOwner).DeleteState(FState);
  FState := IntToStr(udFillPosition.Position);

  // Get selected colour
  Colours := ApplicationManagerInstance.ThemeManager.VisualDescriptor.ColourList;
  Colour := Colours.GetObject(Self.GetComboValue(ecFillColour));

  // Add new colour object instance
  if Assigned(Colour) then
    TAHMFillColourList(FOwner).AddObject(FState, Colour);
end;

procedure TfrmObjectProperties.PopulateStateObject;
var
  Objects: TAHMUIObjectList;
  ObjectType: TAHMUIObjectType;
  UIObject: TAHMUIObject;
begin
  // Remove existing state object instance from state list
  if not FAddingMode then TAHMUIStateObjectList(FOwner).DeleteState(FState);
  FState := ecStateName.Text;

  // Determine selected object type & get appropriate list
  with ecStateType do
    if ItemIndex < 0 then ObjectType := otNone
                     else ObjectType := TAHMUIObjectType(Items.Objects[ItemIndex]);
  Objects := ApplicationManagerInstance.ThemeManager.ThemeObjects[ObjectType];
  UIObject := Objects.GetObject(Self.GetComboValue(ecStateObject));

  // Add new state object instance
  if Assigned(UIObject) then
    TAHMUIStateObjectList(FOwner).AddObject(FState, UIObject);
end;

procedure TfrmObjectProperties.ConfigureAnimationControls;
begin
  // Lets assume we want to hide all controls first
  txAnimationParam1.Visible := False;
  txAnimationParam2.Visible := False;
  txAnimationParam3.Visible := False;
  edAnimationParam1.Visible := False;
  edAnimationParam2.Visible := False;
  edAnimationParam3.Visible := False;
  ecAnimationParam1.Visible := False;
  ecAnimationParam2.Visible := False;

  // Configure parameters for selected animation
  with ApplicationManagerInstance, ApplicationManagerInstance.ThemeManager,
       TAHMAnimation(FInstance).Parameters do
    case TAHMAnimationType(Succ(ecAnimationType.ItemIndex)) of
      atSize:
      begin
        txAnimationParam1.Visible := True;
        txAnimationParam2.Visible := True;
        edAnimationParam1.Visible := True;
        edAnimationParam2.Visible := True;
        txAnimationParam1.Caption := 'Start Size (w,h):';
        txAnimationParam2.Caption := 'Finish Size (w,h):';
        edAnimationParam1.Text := Values[ANIM_PARAM_START_SIZE];
        edAnimationParam2.Text := Values[ANIM_PARAM_FINISH_SIZE];
      end;
      atSlide, atRotate:
      begin
        txAnimationParam1.Visible := True;
        txAnimationParam2.Visible := True;
        ecAnimationParam1.Visible := True;
        ecAnimationParam2.Visible := True;
        txAnimationParam1.Caption := 'Start Place:';
        txAnimationParam2.Caption := 'Finish Place:';
        PopulateCombo(ecAnimationParam1, Values[ANIM_PARAM_START_POS], InterfaceDescriptor.PlaceList, True);
        PopulateCombo(ecAnimationParam2, Values[ANIM_PARAM_FINISH_POS], InterfaceDescriptor.PlaceList, True);
      end;
      atScale:
      begin
        txAnimationParam1.Visible := True;
        txAnimationParam2.Visible := True;
        edAnimationParam1.Visible := True;
        edAnimationParam2.Visible := True;
        txAnimationParam1.Caption := 'Start Scale:';
        txAnimationParam2.Caption := 'Finish Scale:';
        edAnimationParam1.Text := Values[ANIM_PARAM_START_SCALE];
        edAnimationParam1.Text := Values[ANIM_PARAM_FINISH_SCALE];
      end;
      atFadeIn, atFadeOut:
      begin
        txAnimationParam1.Visible := True;
        txAnimationParam2.Visible := True;
        ecAnimationParam1.Visible := True;
        ecAnimationParam2.Visible := True;
        txAnimationParam1.Caption := 'Start Gamma:';
        txAnimationParam2.Caption := 'Finish Gamma:';
        PopulateCombo(ecAnimationParam1, Values[ANIM_PARAM_START_GAMMA], VisualDescriptor.ColourList, True);
        PopulateCombo(ecAnimationParam2, Values[ANIM_PARAM_FINISH_GAMMA], VisualDescriptor.ColourList, True);
      end;
      atMacro:
      begin
        txAnimationParam1.Visible := True;
        ecAnimationParam1.Visible := True;
        txAnimationParam1.Caption := 'Macro:';
        PopulateCombo(ecAnimationParam1, Values[ANIM_PARAM_MACRO_NAME], InterfaceDescriptor.MacroList, True);
      end;
      atFunction:
      begin
        txAnimationParam1.Visible := True;
        txAnimationParam2.Visible := True;
        txAnimationParam3.Visible := True;
        ecAnimationParam1.Visible := True;
        edAnimationParam2.Visible := True;
        edAnimationParam3.Visible := True;
        txAnimationParam1.Caption := 'Function:';
        txAnimationParam2.Caption := 'Target:';
        txAnimationParam3.Caption := 'Parameter:';
        PopulateCombo(ecAnimationParam1, Values[ANIM_PARAM_FUNCTION_NAME], FunctionDescriptor.FunctionList);
        edAnimationParam2.Text := Values[ANIM_PARAM_FUNCTION_TARGET];
        edAnimationParam3.Text := Values[ANIM_PARAM_FUNCTION_PARAM];
      end;
    end;
end;

procedure TfrmObjectProperties.ConfigureStateControls;
var
  ObjectType: TAHMUIObjectType;
  Objects: TAHMUIObjectList;
begin
  // Determine selected object type & get appropriate list
  with ecStateType do
    if ItemIndex < 0 then ObjectType := otNone
                     else ObjectType := TAHMUIObjectType(Items.Objects[ItemIndex]);
  Objects := ApplicationManagerInstance.ThemeManager.ThemeObjects[ObjectType];

  // Populate object name with appropriate object types
  if FAddingMode then PopulateCombo(ecStateObject, nil, Objects, True)
                 else PopulateCombo(ecStateObject, FInstance, Objects, True);
end;

procedure TfrmObjectProperties.LoadImages;
begin
  with FHeaderImages do
  begin
    Clear;
    Width := 150; Height := 57;

    AddResourcePng('HD_IMG_GENERIC'); //0
  end;
end;

end.
